from __future__ import with_statement
import glob
import os.path
import re
import os
import subprocess

sourceRoot ="./"
tempPath = "./temp.tmp"
targetRoot = "../src/generatedTests/"
haskellCodeRoot = "../src/"
allTestsPath = "../src/generatedTests/generatedTests.hs"

def basicName(sourcePath):
    return os.path.splitext(os.path.basename(sourcePath))[0]

def moduleName(sourcePath):
    return "GeneratedTests." + basicName(sourcePath).capitalize()


def toTargetPath(sourcePath):
    return targetRoot + basicName(sourcePath) + ".hs"

def getTime(file):
    if os.path.exists(file):
        targetFiletime = os.path.getmtime(file)
    else:
        targetFiletime = 0
    return targetFiletime

def countReturn(str):
    return len(re.findall("\n", str))

allBasicNames = []
for sourcePath in glob.glob(sourceRoot + "*.test"):
    allBasicNames.append(basicName(sourcePath))
    targetPath = toTargetPath(sourcePath)
    if (os.path.getmtime(sourcePath) < getTime(targetPath)):
        continue
    with open(sourcePath, 'r') as file:
        file = file.read()
    sections = re.split("(\#\#[\w ]+\:)", file)
    try:
        with open(tempPath, 'w') as temp:
            temp.write(sections[0])
        subprocess.call(["runhaskell", "-i" + haskellCodeRoot, "TestCompiler", tempPath, moduleName(sourcePath), targetPath])
    finally:
        os.remove(tempPath)
    
    with open(targetPath, 'a') as targetFile:
        targetFile.write(basicName(sourcePath).lower() + " = [\n")
        i = 1
        currentLine = countReturn(sections[0]) + 1
        
        first = True
        def writeLabel(currentLine):
            global first
            if first:
                first = False
            else:
                targetFile.write(",\n")     
            targetFile.write("    \"" + sourcePath.replace("\\", "\\\\") + "(" + str(currentLine) + ")\" ~: ")
        def writeValues(values):
            targetFile.write(" @@ \"" + values.replace("\n", "") + "\"")
        def writeUpdates(updates):
            targetFile.write(" $$ \"" + updates.replace("\n", "") + "\"")
        while i < len(sections):
            header = sections[i][2:-1].strip()
            i += 1
            content = sections[i].strip()
            i += 1
            if header == "set values":
                values = content
            elif header == "sync":
                updates = content
            elif header == "check values" :
                writeLabel(currentLine)
                targetFile.write("assertSuccess mainSync")
                writeValues(values)
                writeUpdates(updates)
                writeValues(content)
            elif header == "check updates" :
                writeLabel(currentLine)
                targetFile.write("assertSuccessUpdate mainSync")
                writeValues(values)
                writeUpdates(updates)
                writeUpdates(content)
            elif header == "fail":
                writeLabel(currentLine)
                targetFile.write("assertConflict mainSync")
                writeValues(values)
                writeUpdates(content)
            currentLine += countReturn(sections[i-1]) + countReturn(sections[i-2]) 
        targetFile.write("]")
    
with open(allTestsPath, 'w') as testFile:
    testFile.write("module ")
    testFile.write(moduleName(allTestsPath))
    testFile.write(" where\n")
    for name in allBasicNames:
        testFile.write("import " + moduleName(name) + "\n")
    testFile.write(basicName(allTestsPath) + " = ")
    if len(allTestsPath) > 0:
        testFile.write(allBasicNames[0].lower())
        for i in range(1, len(allBasicNames)):
            testFile.write(" ++ " + allBasicNames[i].lower())
    testFile.write("\n")        
    
     